Title Banner

Previous Book Contents Book Index Next

Inside Macintosh: OpenDoc Programmer's Guide / Part 2 - Programming
Chapter 10 - Extending OpenDoc


The OpenDoc Extension Interface

You can greatly extend the capabilities of your parts, in terms of fast processing of information or communication with other parts, if you use the interface-
extension capabilities of OpenDoc. The extension protocol allows parts or other OpenDoc objects to increase their capabilities by extending their programming interfaces. By using extension interfaces, your parts can communicate with other parts or other kinds of OpenDoc components in ways not possible with the standard OpenDoc programming interface.

The semantic interface extension to OpenDoc, described in Chapter 9, "Semantic Events and Scripting," is an example of the use of extensions to support scripting. Other kinds of extension interfaces can be especially valuable in those situations where scripting cannot provide enough integration or bandwidth.

You design, create, and attach such an extension to your part editor. At runtime, other parts can then access and use the extension interface by passing its extension name to method calls to your parts.

Extension Objects

All subclasses of ODObject, including shapes, facets, documents, windows, frames, and parts, can be extended. An extension is itself an object, an instantiation of a subclass of ODExtension. Each extension object is related to its base object--the object whose interface it extends--by its extension name, an ISO string. A caller accesses a base object's extension through that extension name. (Base object in this sense has nothing to do with inheritance; this book uses the term superclass to describe an ancestor in the class hierarchy.) For example, the extension name for the semantic interface extension to a part is kODExtSemanticInterface.

Extensible objects create and delete their own extensions and manage the extensions' storage. If desired, a base object can share an extension object among multiple clients (callers), perhaps using a reference-counting scheme to decide when to delete the extensions. A caller can query an extensible object to see if it supports a specified extension.

The ODExtension class itself has minimal functionality. It is a superclass for subclasses that implement actual extension interfaces. Every extension object knows what base object it is an extension of.

Using an Extension

To access the extension interface of an extensible part, a client, or caller, takes these steps:

  1. It calls the part's override of its inherited HasExtension method to see if the extension is supported, passing the part (the base object) an extension name.
  2. If the part has such an extension, the client then calls the part's (override of its inherited) AcquireExtension method to get a reference to the extension object. The part either creates the extension object or increases its reference count (if the object already exists) and passes the reference back to the client.
  3. The client makes extension-interface calls directly to the extension object.

When the client has finished using the services of the extension object, it takes these steps:

  1. The client calls the extension's (override of its inherited) Release method, to let the extension know that the client no longer needs it.
  2. The extension in turn calls the (override of its inherited) ReleaseExtension method of its part (its base object) if its reference count has dropped to 0. The base object can then delete the extension.

    However, if the extension's base object has already been deleted and has called the extension's BaseRemoved method (see "Closing Your Part"), the extension cannot call its base's ReleaseExtension method.

Implementing Extensions

Your part editors can implement any kinds of desired extension interfaces through this mechanism. The capabilities gained through extensions can be in almost any area. Examples include extensions to handle text search, spell checking, linking, specialized text formatting, database access, and specialized graphics processing. In general, extension objects are best suited for tasks requiring high bandwidth or tight integration, for which scripting is not appropriate.

If you implement an extension object for your part, the extension should include a System Object Model (SOM) constructor (somInit), a SOM destructor (somUninit), and an initialization (InitExtension) method. The extension could also support a GetBase method, through which a client can obtain a reference to the extension's base object. (The ODExtension class provides a default implementation for GetBase.)

Your part is the factory for its extensions, which are reference-counted objects. You must follow the procedures described in the section "Factory Methods" when creating, managing, and deleting extensions. Also, if your part's document is closed while it has extensions remaining in memory, your part's ReleaseAll method must call the extensions' BaseRemoved method.

An extension object must always be valid (attached to its base object) to be used. If a client tries to access an invalid extension, a kODErrInvalidExtension exception is generated. Any time after your part, as base object, calls its extension's BaseRemoved method, the extension is invalid. If you want to provide your own validation scheme for extensions, you need to override the ODExtension methods CheckValid, IsValid, and BaseRemoved.

Your extension interfaces can be private to your parts, or you can establish or follow public standards. CI Labs is the agency responsible for coordinating standard extension interfaces for parts. For information on existing extension interfaces, or to propose new interfaces, please contact CI Labs at the address shown in the section "Cross-Platform Consistency and CI Labs"


Previous Book Contents Book Index Next

© Apple Computer, Inc.
16 JUL 1996




Navigation graphic, see text links

Main | Page One | What's New | Apple Computer, Inc. | Find It | Contact Us | Help